package xhq.com.test.extspring.bean;

import com.google.common.base.CaseFormat;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
import org.springframework.beans.factory.support.BeanDefinitionRegistryPostProcessor;
import org.springframework.stereotype.Component;
import xhq.com.test.extspring.bean.model.MyBeanClass;
import xhq.com.test.extspring.bean.model.MyBeanClassTwo;

/**
 * 通过 注解 @Component 即可被 springboot 创建并执行
 * @author hq_xu
 * @since 2021/1/26 8:40
 */
@Component
public class MyBeanDefinitionRegistryPostProcessor implements BeanDefinitionRegistryPostProcessor {

    /**
     * 这个方法执行前所有常规的BeanDefinition已经被加载到BeanDefinitionRegistry接口实现类中，但还没有bean被实例化
     */
    @Override
    public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry beanDefinitionRegistry) throws BeansException {
        System.out.println("from postProcessBeanDefinitionRegistry");
        // 添加一个 bean 注册
        var myBeanDifinition = BeanDefinitionBuilder.rootBeanDefinition(MyBeanClass.class)
                .addPropertyValue("familyName", "su")
                .addPropertyValue("givenName", "lulu")
                .getBeanDefinition();
        beanDefinitionRegistry.registerBeanDefinition("MyBeanClass", myBeanDifinition);

        // 修改一个存在的 bean 定义
        var beanName = CaseFormat.UPPER_CAMEL.to(CaseFormat.LOWER_CAMEL, MyBeanClassTwo.class.getSimpleName());
        var existBeanDefinition = beanDefinitionRegistry.getBeanDefinition(beanName);
        existBeanDefinition.getPropertyValues().add("familyName", "su");
    }

    @Override
    public void postProcessBeanFactory(ConfigurableListableBeanFactory configurableListableBeanFactory) throws BeansException {
        System.out.println("from postProcessBeanFactory");
        // 如果把下面的代码放开，会导致 bean 的提前创建，最后导致 这些提前创建的 bean 不会走到 InstantiationAwareBeanPostProcessor 接口实现类
        /*var myBean = configurableListableBeanFactory.getBean(MyBeanClass.class);
        var myName = myBean.getName();
        System.out.println(myName);
        System.out.println(myBean.hashCode());

        var myBean2 = configurableListableBeanFactory.getBean(MyBeanClassTwo.class);
        var myName2 = myBean2.getName();
        System.out.println(myName2);*/
    }
}
